package teacher;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import applicationDAO.Institute;

import com.project.trac.R;

import core.modules.DatabaseConnector;

public class UploadForm extends Institute {

	/*
	 *  File Browsing Variables
	 *  */
	private File root = new File(Environment.getExternalStorageDirectory() + "");
	
	// logger
//	private final String TAG = "F_PATH";
	
	// Stores names of traversed directories
	private ArrayList<String> pushDirectory = new ArrayList<String>();

	// Check if the first level of the directory structure is the one showing
	private Boolean firstLvl = true;
	
	private String chosenFile;
	
	private String FILE_PATH;
	
	private Item[] items;

	private int serverResponseCode = 0;
	
	private final int DIALOG_LOAD_FILE = 1000;

	// UI Components 
	private ProgressDialog progressDialog;
	private ListAdapter adapter;
	private TextView filePath;

	private Spinner spinner;
	
	private TextView result;
	
	private List<String> cat_list = new ArrayList<String>();
	private List<String> id_list = new ArrayList<String>();
	
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.layout_uploader);
		setTitle("Upload a Document");
		
		new AsynchronousTask().execute();
		
		spinner = (Spinner) findViewById(R.id.spinner_subject);
		spinner.setOnItemSelectedListener(new OnItemSelectedListener() {

			public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
				setSubjectID(id_list.get(cat_list.indexOf(parent.getItemAtPosition(position).toString())));
			}

			@Override
			public void onNothingSelected(AdapterView<?> arg0) { }
		});
		
		
		filePath = (TextView) findViewById(R.id.filePath);
		result  = (TextView) findViewById(R.id.result);
		result.setTypeface(result.getTypeface(), Typeface.ITALIC);
		result.setTextColor(Color.RED);

		findViewById(R.id.btn_upload).setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				
				progressDialog = ProgressDialog.show(UploadForm.this, "", "Uploading " + chosenFile, true);

				new Thread(new Runnable() {
					public void run() {
						runOnUiThread(new Runnable() {
							public void run() {
								Toast.makeText(getApplicationContext(),"File upload started.", Toast.LENGTH_SHORT).show();
							}
						});
						uploadFile(FILE_PATH);
					}
				}).start();
			}
		});

		findViewById(R.id.btn_browse).setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				loadFileList();
				showDialog(DIALOG_LOAD_FILE);
				//TODO: get file size; file !> 2mb in size
			}
		});
	}

	private int uploadFile(String targetUploadFile) {
		
		//TODO: does not upload to file server
		//TODO: need to insert in table/database
		
		HttpURLConnection connection = null;
		DataOutputStream outputStream = null;

		String lineEnd = "\r\n";
		String twoHyphens = "--";
		String boundary = "*****";

		int bytesRead, bytesAvailable, bufferSize;
		byte[] buffer;
		int maxBufferSize = 1 * 1024 * 1024;

		try {
			FileInputStream fileInputStream = new FileInputStream(new File(targetUploadFile));

			URL url = new URL(DatabaseConnector.getWebUploader());
			connection = (HttpURLConnection) url.openConnection();

			// Allow Inputs & Outputs
			connection.setDoInput(true);
			connection.setDoOutput(true);
			connection.setUseCaches(false);

			// Enable POST method
			connection.setRequestMethod("POST");

			connection.setRequestProperty("Connection", "Keep-Alive");
			connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);

			outputStream = new DataOutputStream(connection.getOutputStream());
			outputStream.writeBytes(twoHyphens + boundary + lineEnd);
			outputStream.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\"" + targetUploadFile + "\"" + lineEnd);
			outputStream.writeBytes(lineEnd);

			bytesAvailable = fileInputStream.available();
			bufferSize = Math.min(bytesAvailable, maxBufferSize);
			buffer = new byte[bufferSize];

			// Read file
			bytesRead = fileInputStream.read(buffer, 0, bufferSize);

			while (bytesRead > 0) {
				outputStream.write(buffer, 0, bufferSize);
				bytesAvailable = fileInputStream.available();
				bufferSize = Math.min(bytesAvailable, maxBufferSize);
				bytesRead = fileInputStream.read(buffer, 0, bufferSize);
			}

			outputStream.writeBytes(lineEnd);
			outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

			// Responses from the server (code and message)
			serverResponseCode = connection.getResponseCode();

			fileInputStream.close();
			outputStream.flush();
			outputStream.close();

			if (serverResponseCode == 200) {
				result.setText("Upload complete.");
				result.setTypeface(result.getTypeface(), Typeface.BOLD);
			}

		} catch (MalformedURLException ex) {

			progressDialog.dismiss();
			ex.printStackTrace();

			result.setText("An error occurred!");
			
			Log.e("Upload file to server", "error: " + ex.getMessage(), ex);
		} catch (Exception e) {
			progressDialog.dismiss();
			result.setText("An unknown error occurred!");
			Log.e("Upload file to server Exception", "Exception : " + e.getMessage(), e);
		}
		
		progressDialog.dismiss();
		
		return serverResponseCode;

	}

	private void loadFileList() {
		
		try {
			root.mkdirs();
		} catch (SecurityException e) {
//			Log.e(TAG, "unable to write on the sd card ");
			Toast.makeText(UploadForm.this, "Unable to write on the SD card.", Toast.LENGTH_SHORT).show();
		}

		// Checks whether path exists
		if (root.exists()) {
			FilenameFilter filter = new FilenameFilter() {
				@Override
				public boolean accept(File dir, String filename) {
					File sel = new File(dir, filename);
					// Filters based on whether the file is hidden or not
					return (sel.isFile() || sel.isDirectory())
							&& !sel.isHidden();

				}
			};

			String[] fList = root.list(filter);
			items = new Item[fList.length];
			for (int i = 0; i < fList.length; i++) {
				items[i] = new Item(fList[i], R.drawable.generic_file);

				// Convert into file path
				File sel = new File(root, fList[i]);

				// Set drawables
				if (sel.isDirectory()) {
					items[i].icon = R.drawable.generic_directory;
					Log.d("DIRECTORY", items[i].file);
				} else {
					Log.d("FILE", items[i].file);
				}
			}

			if (!firstLvl) {
				Item temp[] = new Item[items.length + 1];
				for (int i = 0; i < items.length; i++) {
					temp[i + 1] = items[i];
				}
				temp[0] = new Item("Up", R.drawable.icon_up);
				items = temp;
			}
		} else {
//			Log.e(TAG, "path does not exist");
			Toast.makeText(UploadForm.this, "Invalid file path.", Toast.LENGTH_SHORT).show();
		}

		adapter = new ArrayAdapter<Item>(this,android.R.layout.select_dialog_item, android.R.id.text1,items) {
			@Override
			public View getView(int position, View convertView, ViewGroup parent) {
				// creates view
				View view = super.getView(position, convertView, parent);
				TextView textView = (TextView) view.findViewById(android.R.id.text1);

				// put the image on the text view
				textView.setCompoundDrawablesWithIntrinsicBounds(items[position].icon, 0, 0, 0);

				// add margin between image and text (support various screen
				// densities)
				int dp5 = (int) (5 * getResources().getDisplayMetrics().density + 0.5f);
				textView.setCompoundDrawablePadding(dp5);

				return view;
			}
		};

	}

	@Override
	protected Dialog onCreateDialog(int id) {
		Dialog dialog = null;
		AlertDialog.Builder builder = new Builder(this);

		if (items == null) {
//			Log.e(TAG, "No files loaded");
			
			Toast.makeText(UploadForm.this,
					"No file selected.", Toast.LENGTH_SHORT).show();
			
			dialog = builder.create();
			return dialog;
		}

		switch (id) {
		case DIALOG_LOAD_FILE:
			builder.setTitle("Browse for file");
			builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int which) {
					chosenFile = items[which].file;
					File sel = new File(root + "/" + chosenFile);
					if (sel.isDirectory()) {
						firstLvl = false;

						// Adds chosen directory to list
						pushDirectory.add(chosenFile);
						items = null;
						root = new File(sel + "");

						loadFileList();

						removeDialog(DIALOG_LOAD_FILE);
						showDialog(DIALOG_LOAD_FILE);
//						Log.d(TAG, root.getAbsolutePath());

					}

					// Checks if 'up' was clicked
					else if (chosenFile.equalsIgnoreCase("up") && !sel.exists()) {

						// present directory removed from list
						String s = pushDirectory.remove(pushDirectory.size() - 1);

						// path modified to exclude present directory
						root = new File(root.toString().substring(0,root.toString().lastIndexOf(s)));
						items = null;

						// if there are no more directories in the list, then
						// its the first level
						if (pushDirectory.isEmpty()) {
							firstLvl = true;
						}
						loadFileList();

						removeDialog(DIALOG_LOAD_FILE);
						showDialog(DIALOG_LOAD_FILE);
						//Log.d(TAG, root.getAbsolutePath());

					}
					// File picked
					else {
						FILE_PATH = root.getAbsolutePath().concat("/" + chosenFile);
						
						filePath.setText(chosenFile);
						//Log.i("ELSE - CURRENT DIR", root.getAbsolutePath());
						//Log.i("The Chosen File", chosenFile);
						//Log.i("filePath.getText", filePath.getText().toString());
						//Toast.makeText(UploadForm.this, chosenFile, Toast.LENGTH_SHORT).show();
					}

				}
			});
			break;
		}
		dialog = builder.show();
		return dialog;
	}

	private class Item {
		
		private String file;
		private int icon;

		public Item(String file, Integer icon) {
			this.file = file;
			this.icon = icon;
		}

		@Override
		public String toString() {
			return file;
		}
	}

	private class AsynchronousTask extends AsyncTask<String, String, String> {
		
		ArrayAdapter<String> arrayAdapter;
		HashMap<String, String> m;

		String KEY_FILENAME = "k1";
		String KEY_LOCATION = "k2";
		
		

		ResultSet rs;

		protected void onPreExecute() {
			super.onPreExecute();
		}

		protected String doInBackground(String... args) {
			try {

				rs = DatabaseConnector.getStatement().executeQuery(
						"SELECT schedule.id, curriculum.catalognumber"
						+ " FROM schedule"
						+ " INNER JOIN curriculum ON curriculum.id = schedule.catalognumber"
						+ " WHERE creator = " + getUserID());

				while (rs.next()) {

					m = new HashMap<String, String>();
					m.put(rs.getString("id"), rs.getString("catalognumber"));

					cat_list.add(rs.getString("catalognumber"));
					id_list.add(rs.getString("id"));
				}

		} catch (SQLException e) {
			Log(getClass(), "doInBackground", e);
		} 

			return null;
		}

		protected void onPostExecute(String postExecute) {

			runOnUiThread(new Runnable() {

				public void run() {

					arrayAdapter = new ArrayAdapter<String>(
							UploadForm.this,
							android.R.layout.simple_spinner_item, cat_list);
					arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
					spinner.setAdapter(arrayAdapter);
				}
			});
			
		}
	}
}